package com.ruoyi.common.utils;

import javax.imageio.*;
import javax.imageio.stream.*;
import javax.imageio.metadata.*;
import javax.imageio.ImageTypeSpecifier;
import org.w3c.dom.*;
import java.io.*;
import java.awt.image.*;
import java.util.*;

public class BatchDPIChanger{

    // 固定参数 - 修改这里设置输入输出路径和DPI
    private static final String INPUT_FOLDER = "C:\\Users\\xinhuiRong\\Desktop\\未命名文件夹 2\\未命名文件夹 2";
    private static final String OUTPUT_FOLDER = "C:\\Users\\xinhuiRong\\Desktop\\dpi";
    private static final int TARGET_DPI = 300;
    private static final Set<String> SUPPORTED_FORMATS = new HashSet<>(Arrays.asList(
            "jpg", "jpeg", "png", "dng", "tif", "tiff"
    ));

    public static void main(String[] args) {
        try {
            File inputFolder = new File(INPUT_FOLDER);
            File outputFolder = new File(OUTPUT_FOLDER);

            if (!inputFolder.exists()) {
                System.err.println("错误：输入文件夹不存在 - " + INPUT_FOLDER);
                return;
            }

            if (!outputFolder.exists()) {
                if (outputFolder.mkdirs()) {
                    System.out.println("已创建输出文件夹 - " + OUTPUT_FOLDER);
                } else {
                    System.err.println("无法创建输出文件夹 - " + OUTPUT_FOLDER);
                    return;
                }
            }

            processFolder(inputFolder, outputFolder, TARGET_DPI);
            System.out.println("\n处理完成！");
            System.out.println("输入文件夹: " + INPUT_FOLDER);
            System.out.println("输出文件夹: " + OUTPUT_FOLDER);
            System.out.println("设置的DPI值: " + TARGET_DPI);
        } catch (Exception e) {
            System.err.println("程序执行出错: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private static void processFolder(File inputFolder, File outputFolder, int dpi) throws IOException {
        File[] files = inputFolder.listFiles();
        if (files == null) return;

        for (File file : files) {
            if (file.isDirectory()) {
                File subFolder = new File(outputFolder, file.getName());
                if (!subFolder.exists()) subFolder.mkdirs();
                processFolder(file, subFolder, dpi);
            } else {
                processImageFile(file, outputFolder, dpi);
            }
        }
    }

    private static void processImageFile(File inputFile, File outputFolder, int dpi) {
        try {
            String fileName = inputFile.getName();
            String fileExt = getFileExtension(fileName).toLowerCase();

            // 检查是否支持的格式
            if (!SUPPORTED_FORMATS.contains(fileExt)) {
                System.out.println("跳过不支持的文件: " + fileName);
                return;
            }

            // 读取原始图片
            BufferedImage image = ImageIO.read(inputFile);
            if (image == null) {
                System.err.println("无法读取图片: " + fileName);
                return;
            }

            // 准备输出文件
            File outputFile = new File(outputFolder, fileName);
            String formatName = fileExt.equals("jpg") ? "jpeg" : fileExt;

            // 获取图片写入器
            ImageWriter writer = getImageWriter(formatName);
            if (writer == null) {
                System.err.println("找不到适合的写入器: " + fileName);
                return;
            }

            // 创建输出流
            ImageOutputStream ios = ImageIO.createImageOutputStream(outputFile);
            writer.setOutput(ios);

            // 获取写入参数
            ImageWriteParam writeParam = writer.getDefaultWriteParam();

            // 获取和设置元数据（关键修正点）
            ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromRenderedImage(image);
            IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);

            // 根据格式设置DPI
            if (formatName.equalsIgnoreCase("tiff") || formatName.equalsIgnoreCase("dng")) {
                setTiffDpiMetadata(metadata, dpi);
            } else {
                setStandardDpiMetadata(metadata, dpi);
            }

            // 写入图片
            writer.write(null, new IIOImage(image, null, metadata), writeParam);

            // 清理资源
            writer.dispose();
            ios.close();

            System.out.println("成功处理: " + fileName);
        } catch (Exception e) {
            System.err.println("处理文件出错 " + inputFile.getName() + ": " + e.getMessage());
        }
    }

    private static String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf('.');
        return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1);
    }

    private static ImageWriter getImageWriter(String formatName) {
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
        return writers.hasNext() ? writers.next() : null;
    }

    private static void setStandardDpiMetadata(IIOMetadata metadata, int dpi) throws IIOInvalidTreeException {
        // 计算像素大小 (mm/像素) = 25.4mm / DPI
        double pixelSizeMM = 25.4 / dpi;

        // 获取元数据格式
        String metaFormatName = metadata.getNativeMetadataFormatName();
        if (metaFormatName == null) {
            metaFormatName = "javax_imageio_1.0";
        }

        // 获取元数据树
        Node rootNode = metadata.getAsTree(metaFormatName);

        // 设置水平和垂直像素大小
        setMetadataNodeValue(rootNode, "HorizontalPixelSize", Double.toString(pixelSizeMM));
        setMetadataNodeValue(rootNode, "VerticalPixelSize", Double.toString(pixelSizeMM));

        // 将修改后的树合并回元数据
        metadata.mergeTree(metaFormatName, rootNode);
    }

    private static void setTiffDpiMetadata(IIOMetadata metadata, int dpi) throws IIOInvalidTreeException {
        // 获取TIFF元数据格式
        String metaFormatName = metadata.getNativeMetadataFormatName();
        if (metaFormatName == null) {
            metaFormatName = "javax_imageio_1.0";
        }

        Node rootNode = metadata.getAsTree(metaFormatName);

        // 查找或创建TIFF IFD节点
        Node ifdNode = findOrCreateNode(rootNode, "TIFFIFD");

        // 设置X和Y分辨率 (DPI)
        setTiffResolutionNode(ifdNode, "XResolution", dpi);
        setTiffResolutionNode(ifdNode, "YResolution", dpi);

        // 设置分辨率单位为英寸 (2表示英寸，1表示厘米)
        setMetadataNodeValue(ifdNode, "ResolutionUnit", "2");

        // 将修改后的树合并回元数据
        metadata.mergeTree(metaFormatName, rootNode);
    }

    private static void setTiffResolutionNode(Node parentNode, String nodeName, int dpi) {
        Node resolutionNode = findOrCreateNode(parentNode, nodeName);
        Node rationalNode = findOrCreateNode(resolutionNode, "TIFFRational");

        setMetadataNodeValue(rationalNode, "Numerator", Integer.toString(dpi));
        setMetadataNodeValue(rationalNode, "Denominator", "1");
    }

    private static Node findOrCreateNode(Node parent, String nodeName) {
        NodeList childNodes = parent.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node node = childNodes.item(i);
            if (node.getNodeName().equalsIgnoreCase(nodeName)) {
                return node;
            }
        }

        // 如果节点不存在则创建新节点
        Element newNode = parent.getOwnerDocument().createElement(nodeName);
        return parent.appendChild(newNode);
    }

    private static void setMetadataNodeValue(Node parent, String nodeName, String value) {
        Node node = findOrCreateNode(parent, nodeName);

        // 确保"value"属性存在
        Attr valueAttr = node.getOwnerDocument().createAttribute("value");
        if (node.getAttributes().getNamedItem("value") != null) {
            node.getAttributes().removeNamedItem("value");
        }
        valueAttr.setNodeValue(value);
        node.getAttributes().setNamedItem(valueAttr);
    }
}